#include <stdlib.h>

#include "lib.h"
#include "lirsql.h"
#include "lirgame.h"
#include "lirsaved.h"
#include "odbc.h"
#include "missinggamenums.h"

LIRSQL::LIRSQL(const String & DBDSN, const String & DBLogin,
	const String & DBPassword)
	: ProgressiveTrackSQL(DBDSN, DBLogin, DBPassword)
{
#ifdef USE_MISSINGGAMENUMS
	//missing game nums deleted in TrackSQL::~TrackSQL
	missinggamenums = new MissingGameNums(this, "pub_getTableIdentityLetEmRide");
#endif
}

int32
LIRSQL::createGame(int32 casinoId, PID pid, bool8 forMoney, SESSIONID sessionId,
	int32 compFactor, LIRGameID gid, int32 bet, int32 progressiveBet,
	int32 multiBankBet, int32* balance, int32* comp, uint8 payTable)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_CreateGameLetEmRide ");
		query->addParam(casinoId);
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(sessionId, ODBCQuery::NOQUOTES);
		query->addParam(compFactor);
		query->addParam(bet, ODBCQuery::MONEY);
		query->addParam(progressiveBet, ODBCQuery::MONEY);   //progressiveBet
		query->addParam(multiBankBet, ODBCQuery::MILLIMONEY);
		query->addParam(payTable);   

		if (query->exec())
		{
			while (query->getRow())
			{
				ok =
					query->getData(1, gid, LIR_GAMEID_SIZE) &&
					query->getData(2, balance, ODBCQuery::MONEY) &&
					query->getData(3, comp);
			}
		}
		delete query;
	}
	delete conn;

	if (ok)
	{
#ifdef USE_MISSINGGAMENUMS
		int32 gamenum = atol(gid);
		if (missinggamenums)
			missinggamenums->setGameNum(gamenum);
#endif
	}

	return ok ? NoError : ExecFailed;
}

int32
LIRSQL::deal(PID pid, LIRGameID gid, int32 nDeckSeed, int32 numPlayer, uint8* player)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_LetEmRideDeal ");
		query->addParam(pid);
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(nDeckSeed);     // kharmon.  10-16-06.  #8226.  Don't store the cards in the record until the game is over.		
		query->addParam(player, numPlayer, ODBCQuery::BINARY);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
LIRSQL::gameDone(int32 casinoId,
	PID pid, bool8 forMoney, LIRGameID gid, bool8 raised,
	int32 payouts[3], int32 payProgressive, int32 payMultiBank, 
	int32 outcome, int32 balanceAdjust, bool8 bMalfunction, 
    int32* balance, int32* comp, int32 numDealer, uint8* dealer,
	int32 numPlayer, uint8* player)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_LetEmRideGameDone ");
		query->addParam(casinoId);
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(raised ? "R" : "P");
		query->addParam(payouts[0], ODBCQuery::MONEY);
		query->addParam(payouts[1], ODBCQuery::MONEY);
		query->addParam(payouts[2], ODBCQuery::MONEY);
		query->addParam(payProgressive, ODBCQuery::MONEY);
		query->addParam(payMultiBank, ODBCQuery::MILLIMONEY);
		query->addParam((uint8)(outcome & 0xffL), ODBCQuery::BINARY);
		query->addParam(balanceAdjust, ODBCQuery::MONEY);
        query->addParam(bMalfunction);                          // kharmon.  01-05-06.  #4250.  Did this game win the big progressive jackpot and thus needs verification?
		query->addParam(dealer, numDealer, ODBCQuery::BINARY);  // kharmon.  10-16-06.  #8226.  Don't store the face down dealer cards in the record until the game is over.
		query->addParam(player, numPlayer, ODBCQuery::BINARY);


		if (query->exec())
		{
			while (query->getRow())
			{
				ok = query->getData(1, balance, ODBCQuery::MONEY) &&
					query->getData(2, comp);
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
LIRSQL::turnOneDone(PID pid, bool8 forMoney, LIRGameID gid, bool8 raised, int32 numDealer, uint8* dealer)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_LetEmRideTurnOneDone ");
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(raised ? "R" : "P");
        query->addParam(dealer, numDealer, ODBCQuery::BINARY);  // kharmon.  11-07-06.  #8226.  Store the new face up dealer card in the db.

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}


int32
LIRSQL::hasSavedGame(PID pid, bool8 forMoney, LIRGameID gid,
	LIRSavedGame* dest, bool8* exists)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	*exists = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_LetEmRideGetSavedGame ");
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));

		if (query->exec())
		{
			int32 hasSaved = 0;
            int32 numchars = 0;

			ok = true;

			while (query->getRow())
			{
				if (query->getData(1, &hasSaved) && hasSaved!=0)
				{
					*exists = true;

                    if(hasSaved==1)
                    {
                        // kharmon.  10-16-06.  #8226.  This game is an older saved game with no deckseed.
                        dest->bHasDeckSeed = false;

					    ok &= query->getData(2, gid, LIR_GAMEID_SIZE);
					    ok &= query->getData(3, &dest->bet, ODBCQuery::MONEY);
					    ok &= query->getData(4, &dest->progressiveBet, ODBCQuery::MONEY);
					    ok &= query->getData(5, dest->dealerCards, MAXDEALERCARDS, &dest->numDealerCards);
					    ok &= query->getData(6, dest->playerCards, MAXPLAYERCARDS, &dest->numPlayerCards);
					    ok &= query->getData(7, &dest->raisePassTurn1, 1, &numchars);
					    ok &= query->getData(8, &dest->payTable);
                        ok &= query->getData(9, &dest->bMalfunction);   // kharmon.  01-05-06.  #4250.
                    }
                    else if(hasSaved==2)
                    {
                        // kharmon.  10-16-06.  #8226.  This saved game has a deckseed.  Use that to restore the cards.
                        dest->bHasDeckSeed = true;

					    ok &= query->getData(2, gid, LIR_GAMEID_SIZE);
					    ok &= query->getData(3, &dest->bet, ODBCQuery::MONEY);
					    ok &= query->getData(4, &dest->progressiveBet, ODBCQuery::MONEY);
                        ok &= query->getData(5, &dest->nDeckSeed);					    
					    ok &= query->getData(6, &dest->raisePassTurn1, 1, &numchars);
					    ok &= query->getData(7, &dest->payTable);
                        ok &= query->getData(8, &dest->bMalfunction);   // kharmon.  01-05-06.  #4250.
                    }
				}
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
LIRSQL::removeSavedGame(PID pid, bool8 forMoney)
{
	//the saved game does not need to be removed because the act of ending the game
	//removes the saved game

	return true;
}

int32
LIRSQL::saveGame(PID pid, bool8 forMoney, LIRGameID gid,
	LIRSavedGame* src)
{
	//the saved game does not need to be saved because the act of creating the game
	//saves game

	return true;
}

int32
LIRSQL::getOptions(uint8& payTable, bool8& progressiveOn, 
				   uint8& progPayTable, uint8& realProgBetPcnt, uint8& funProgBetPcnt, int32& jackpotID, int32& progressiveFixAmountMultiplier)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;
	uint8 bit1=0;
	uint8 tinyint1=0, tinyint2=0, tinyint3=0, tinyint4=0;
	int32 normalint1=0, normalint2=0;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_LetEmRideGetOptions ");

		if (query->exec())
		{
			while (query->getRow())
			{
				ok = query->getData(1, &tinyint1) &&
					 query->getData(2, &bit1)     &&
                     query->getData(4, &tinyint2) &&
					 query->getData(5, &tinyint3) &&
					 query->getData(6, &tinyint4) &&
                     query->getData(8, &normalint1) &&
					 query->getData(9, &normalint2);

				if (ok)
				{
					progressiveOn = (bool8)(bit1 != 0);
					payTable = (uint8)tinyint1;
					progPayTable = (uint8)tinyint2;
					realProgBetPcnt = (uint8)tinyint3;
					funProgBetPcnt = (uint8)tinyint4;
					jackpotID = normalint1;
					progressiveFixAmountMultiplier = normalint2;
				}
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}
